package dao

import (
	"errors"
	"fmt"
	"github.com/zeromicro/go-zero/core/logx"
	"go.mongodb.org/mongo-driver/bson"
	"go.uber.org/zap"
	"homepage_srv/homepage"
	"homepage_srv/model"
	"smart-health-platforms/config"
	"smart-health-platforms/inits"
	"smart-health-platforms/pkg"
	"strconv"
	"strings"
	"time"
)

// 添加一级评论
func AddComment(in *homepage.AddCommentRequest) (*model.Comment, error) {
	collection := config.HealthDB.Collection("comments")
	if err := inits.InitCounter("comments"); err != nil {
		pkg.Error("初始化评论表失败", zap.Error(err))
		return nil, err
	}
	// 获取自增 ID
	seq, err := inits.GetNextID("comments")
	if err != nil {
		pkg.Error("获取自增 ID 失败", zap.Error(err))
		return nil, err
	}
	// 参数验证
	if in.UserId == 0 {
		pkg.Warn("用户ID不能为空")
		return nil, errors.New("用户ID不能为空")
	}
	if in.GoodId == 0 {
		pkg.Warn("商品ID不能为空")
		return nil, errors.New("商品ID不能为空")
	}
	if strings.TrimSpace(in.Content) == "" {
		pkg.Warn("评论内容不能为空")
		return nil, errors.New("评论内容不能为空")
	}
	now := time.Now() //设置当前时间
	// 创建要插入的文档
	commentDoc := bson.M{
		"_id":        seq, // 自增 ID作为 _id
		"user_id":    in.UserId,
		"good_id":    in.GoodId,
		"content":    in.Content,
		"parent_id":  0, // 明确标识这是一级评论
		"created_at": now,
		"replies":    make([]model.Reply, 0), // 初始化空回复数组
	}
	// 插入数据到mongodb
	_, err = collection.InsertOne(config.Ctx, commentDoc)
	if err != nil {
		pkg.Error("插入评论失败", zap.Error(err))
		return nil, err
	}
	// 构建返回的评论对象
	insertedComment := &model.Comment{
		ID:        int64(seq), // 这里需要根据您的 model.Comment 结构体调整
		UserId:    in.UserId,
		GoodId:    in.GoodId,
		Content:   in.Content,
		CreatedAt: now,
		Replies:   make([]model.Reply, 0),
	}
	return insertedComment, nil
}

// 添加一级评论回复
func AddReply(in *homepage.AddReplyRequest) (*model.Reply, error) {
	// 初始化文档
	collection := config.HealthDB.Collection("comments")
	// 参数验证
	if in.UserId == 0 {
		pkg.Warn("用户ID不能为空")
		return nil, errors.New("用户ID不能为空")
	}
	if in.CommentId == "" {
		pkg.Warn("父级评论ID不能为空")
		return nil, errors.New("父评论ID不能为空")
	}
	if strings.TrimSpace(in.Content) == "" {
		pkg.Warn("回复内容不能为空")
		return nil, errors.New("回复内容不能为空")
	}

	now := time.Now()
	// 1. 转换 CommentId 为正确的类型int64
	commentID, err := strconv.ParseInt(in.CommentId, 10, 64)
	if err != nil {
		pkg.Error("父评论ID格式错误", zap.Error(err), zap.String("comment_id", in.CommentId))
		return nil, errors.New("父评论ID格式错误")
	}
	// 2. 检查父评论是否存在
	var parentComment model.Comment
	err = collection.FindOne(config.Ctx, bson.M{"_id": commentID}).Decode(&parentComment)
	if err != nil {
		pkg.Error("查询父评论失败", zap.Error(err), zap.Int64("comment_id", commentID))
		return nil, fmt.Errorf("查询父评论失败: %v", err)
	}
	if commentID == 0 {
		pkg.Error("父评论不存在", zap.Int64("comment_id", commentID))
		return nil, errors.New("父评论不存在")
	}
	// 3. 获取回复ID
	replyID, err := inits.GetNextID("reply_counter")
	if err != nil {
		pkg.Error("获取回复ID失败", zap.Error(err))
		return nil, err
	}
	// 4. 创建回复对象
	newReply := model.Reply{
		ID:        int64(replyID),
		UserId:    in.UserId,
		Content:   in.Content,
		CreatedAt: now,
		CommentId: commentID,
	}
	// 5. 更新父评论，将回复添加到replies数组中
	update := bson.M{
		"$push": bson.M{
			"replies": newReply,
		},
		"$set": bson.M{
			"updated_at": now,
		},
	}
	result, err := collection.UpdateByID(config.Ctx, commentID, update)
	if err != nil {
		logx.Error("添加回复到父评论失败", zap.Error(err), zap.Int64("comment_id", commentID))
		return nil, fmt.Errorf("添加回复失败: %v", err)
	}
	if result.ModifiedCount == 0 {
		logx.Error("更新父评论失败，未修改任何文档", zap.Int64("comment_id", commentID))
		return nil, errors.New("更新父评论失败")
	}
	pkg.Info("回复添加成功",
		zap.Int64("commentId", commentID),
		zap.Int64("id", newReply.ID),
		zap.Int64("userId", in.UserId))
	return &newReply, nil
}

// 查询评论详情,包含评论回复
func GetCommentList(in *homepage.GetCommentsRequest) ([]*model.Comment, error) {
	// 初始化文档
	collection := config.HealthDB.Collection("comments")
	// 构建查询条件，根据商品id查询商品评论
	filter := bson.M{}
	if in.GoodId != 0 {
		filter["good_id"] = in.GoodId
	}
	// 查询评论列表
	cursor, err := collection.Find(config.Ctx, filter)
	if err != nil {
		pkg.Error("查询评论列表失败",
			zap.Error(err),
			zap.Int64("good_id", in.GoodId))
		return nil, fmt.Errorf("查询评论列表失败: %v", err)
	}
	defer cursor.Close(config.Ctx)
	// 解析结果
	var comments []*model.Comment
	if err := cursor.All(config.Ctx, &comments); err != nil {
		pkg.Error("解析评论列表失败",
			zap.Error(err))
		return nil, fmt.Errorf("解析评论列表失败: %v", err)
	}

	// 处理空结果
	if comments == nil {
		comments = make([]*model.Comment, 0)
	}

	// 添加查询结果日志
	pkg.Info("查询到的评论列表",
		zap.Int("count", len(comments)),
		zap.Int64("good_id", in.GoodId),
		zap.Any("comments", comments))

	return comments, nil
}
